Sesión 8

Curso: Fundamentos R para Ciencia de Datos en Salud


Percy Soto-Becerra, M.D., M.Sc(c)

DIS – IETSI, EsSalud

2024-04-07

  https://github.com/psotob91

Reporte Reproducible

Agenda

  1. Reporte Reproducible

  2. tbl_summary() paso a paso

  3. gtsummary: tbl_summary y argumento by =

  4. Buenas y malas prácticas de reporte en investigación

  5. Misceláneas

Reporte Reproducible

¿Cómo hacer que un análisis de datos sea reproducible?


  • No cree la tabla “manualmente”.

  • Genere las tablas con código:

    • Es reproducible.
    • Menos propenso a error de digitación o lapsus calamis.
    • Han habido retracciones de ensayos clínicos por errores de tipeo!!
    • Es más rápido, ahorrarás tiempo!!

R integra el reporte en todo el flujo de trabajo reproducible


Tablas descriptivas


  • En un artículo estas pueden variar entre disciplinas y dependiendo lo qu e se desee comunicar.

  • En investigación en salud, por ejemplo, a la tabla descriptiva menudo se la conoce como tablas tipo 1.

    • Puede haber más de una, no hay reglas, solo buenos o malos criterios para presentar resultados.

    • A veces separan la tabla 1 en Tabla 1 (toda la población) y tabla 2 (comparación de características)

  • Hay muchos paquetes: {flextable}, {gt},{huxtable}, {kableExtra}, {kable}, etc.

  • Sugerimos {gtsummary} para comenzar: https://www.danieldsjoberg.com/gtsummary/

Tablas reproducibles en R


  • Paquetes para construir tablas personalizadas paso a paso:

    • {flextable}
    • {gt}
    • {huxtable}
    • {kable}
    • {kableExtra}
  • Paquetes para construir tablas pre-definidas de manera rápida:

    • {gtsummary}
    • Hay varias más, pero no las tengo mapeadas todas… (en una próxima edición)

Tabla decriptiva reproducible con {gtsummary}


  • Permite crear tablas en formato de revistas biomédicas.

  • Función tbl_summary() para tablas descriptivas univariadas y comparativas (bivariadas)

https://www.danieldsjoberg.com/gtsummary/

Los datos que usaremos


  • Usaremos los datos simulados de un ensayo clínico para evaluar la seguridad de un suplemento en outcomes clinico y fisiologicos de mujeres con menopausia:
id time treat treated age race married2 procedence weight height e2
1 Baseline Placebo 0 33 Mestiza Without couple Callao 59.0 1.4 87.30
1 3 months Placebo 0 32 Mestiza Without couple Callao 59.9 1.3 210.05
2 Baseline Dosis 2 1 27 Mestiza Without couple Santa Anita 62.0 1.5 169.01
2 3 months Dosis 2 1 27 Mestiza Without couple Santa Anita 62.1 1.6 99.91
3 Baseline Dosis 1 1 25 Mestiza Without couple Callao 62.0 1.6 78.76
3 3 months Dosis 1 1 25 Mestiza Without couple Callao 60.0 1.6 155.04
  • Las etiquetas de cada variable son:
Variable Label
id ID participant
time Time's measurement
treat Treatment's group
treated Treated
age Age, years
race Race
married2 Marital status, recat
procedence Distrit of procedence
weight Weight, kg
height Height, m
e2 Estradiol

tbl_summary() paso a paso

Agenda

  1. Reporte Reproducible

  2. tbl_summary() paso a paso

  3. gtsummary: tbl_summary y argumento by =

  4. Buenas y malas prácticas de reporte en investigación

  5. Misceláneas

tbl_summary() paso a paso

tbl_summary() básico


  • Seleccionar las variables que desea reportar con función select(), luego usar tbl_summary():
library(gtsummary)
datos %>% 
  select(age, race, married2, e2) %>% 
  tbl_summary()

  • Cuarto tipo de resumenes: continuous, continuos2, categorical y dichotomous

  • Por defecto, los estadísticos son reportadas como mediana (percentil 25, percentil 75) para variables numéricas y n (%) para variables categóricas/dicotómicas.

  • Las variables codificadas como 0 / 1, TRUE / FALSE o Yes / No son tratadas como dicotómicas.

  • Los valores NA se listan como “Unknown

  • Los atributos de etiqueta se imprimen por defecto.

  • Uno puede realizar más personalizaciones a la tabla.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary()

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous")
  )
  • type: Especifica el tipo de variable para el resumen

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    statistic = list(
      age ~ "{mean} ({sd})", 
      married2 ~ "{n}  / {N} ({p}%)"
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    statistic = list(
      c(age, height) ~ "{mean} ({sd})", 
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

    • Usar c() para varias variables.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", 
                         "{median} ({p25} - {p75})"), 
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

    • Usar c() para varias variables.

    • Si queremos reportar más estadísticos en variables numéricas usamos continuous2

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", 
                         "{median} ({p25} - {p75})", 
                         "{min} - {max}"), 
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

    • Usar c() para varias variables.

    • Si queremos reportar más estadísticos en variables numéricas usamos continuous2

      • Podemos ponerle cuantos estadísticos queramos.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})",
                "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    )
  ) 
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

    • Usar c() para varias variables.

    • Si queremos reportar más estadísticos en variables numéricas usamos continuous2

      • Podemos ponerle cuantos estadísticos queramos.

      • Podemos tener diferentes combinaciones de estadísticos.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height, e2) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})",
                "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    ), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

  • label: Cambia o personaliza la etiqueta de la variable.

Personalización del resultado de tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height, e2) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})",
                "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    ), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    digits = list(
      c(age) ~ 1, c(height, e2) ~ 2, c(married2, treated) ~ 1
    )
  )
  • type: Especifica el tipo de variable para el resumen.

  • statistic: Personaliza los estadísticos reportados.

  • label: Cambia o personaliza la etiqueta de la variable.

  • digit: Especifica el número de decimales de redondeo.

Reporte de datos perdidos con tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height, e2) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})", "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    ), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    digits = list(
      c(age) ~ 1, c(height, e2) ~ 2, c(married2, treated) ~ 1
    ), 
    missing_text = "Missing data"
  ) 
  • misisng_text: Permite editar la etiqueta de missing (Unknown por defecto).

Reporte de datos perdidos con tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height, e2) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})", "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    ), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    digits = list(
      c(age) ~ 1, c(height, e2) ~ 2, c(married2, treated) ~ 1
    ), 
    missing = "always", missing_text = "Missing data"
  )  
  • misisng_text: Permite editar la etiqueta de missing (Unknown por defecto).

  • missing: Por defecto se presentan los datos perdidos solo si la variable los tiene “ifany”.

    • missing = “always” siempre presenta datos perdidos.

Reporte de datos perdidos con tbl_summary()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(c(age, height, e2) ~ "continuous2"), 
    statistic = list(
      c(age, height) ~ c("{mean} ({sd})", "{min} - {max}"), 
      c(e2) ~ c("{median} ({p25} - {p75})", "{min} - {max}"),       
      c(married2, treated) ~ "{n}  / {N} ({p}%)"
    ), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    digits = list(
      c(age) ~ 1, c(height, e2) ~ 2, c(married2, treated) ~ 1
    ), 
    missing = "no"
  ) 
  • misisng_text: Permite editar la etiqueta de missing (Unknown por defecto).

  • missing: Por defecto se presentan los datos perdidos solo si la variable los tiene “ifany”.

    • missing = “always” siempre presenta datos perdidos, así la variable no los tenga.
    • missing = “no” nunca presenta datos perdidos, así la variable los tenga.

En resumen: {gtsummary} + fórmulas


Personzalización con bold_() / italicize_()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) 

Personzalización con bold_() / italicize_()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels()
  • bold_labels(): negrita a las etiquetas de las variables

Personzalización con bold_*() / italicize_*()


datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() %>% 
  italicize_levels() 
  • bold_labels(): negrita a las etiquetas de las variables

  • italicize_levels(): cursiva a los niveles (valores) de las variables

Guardar tabla como documento MS Word


  • Se puede descargar la tabla en formato MS. Word para reporte reproducible.

  • Primero se guarda como un objeto de R:

datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() -> tabla1 

tabla1

Guardar tabla como documento MS Word


  • Se puede descargar la tabla en formato MS. Word para reporte reproducible.

  • Primero se guarda como un objeto de R:

datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() -> tabla1 

tabla1

  • Luego, al objeto se lo guarda como un archivo de MS Word.

Guardar tabla como documento MS Word


  • Se puede descargar la tabla en formato MS. Word para reporte reproducible.

  • Primero se guarda como un objeto de R:

datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() -> tabla1 

tabla1

  • Luego, al objeto se lo guarda como un archivo de MS Word.
library(flextable)
  • Paso 1: Cargar paquete {flextable}

Guardar tabla como documento MS Word


  • Se puede descargar la tabla en formato MS. Word para reporte reproducible.

  • Primero se guarda como un objeto de R:

datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() -> tabla1 

tabla1

  • Luego, al objeto se lo guarda como un archivo de MS Word.
library(flextable)

tabla1 %>% 
  as_flex_table() 

Characteristic

N = 1061

Age, years

33.0 (29.0, 37.0)

Treated with supplement

72 (68%)

Marital status

With couple

52 (49%)

Without couple

54 (51%)

Height, m

1.50 (1.50, 1.60)

Unknown

3

Estradiol, UI

92 (59, 132)

1Median (IQR); n (%)

  • Paso 1: Cargar paquete {flextable}

  • Paso 2: Se convierte a objeto de tipo flextable con la función as_flex_table().

Guardar tabla como documento MS Word


  • Se puede descargar la tabla en formato MS. Word para reporte reproducible.

  • Primero se guarda como un objeto de R:

datos %>% 
  select(age, treated, married2, height, e2) %>% 
  tbl_summary(
    type = list(height ~ "continuous"), 
    label = list(
      treated ~ "Treated with supplement", e2 ~ "Estradiol, UI",
      married2 ~ "Marital status"
    ), 
    missing = "ifany"
  ) %>% 
  bold_labels() -> tabla1 

tabla1

  • Luego, al objeto se lo guarda como un archivo de MS Word:
library(flextable)

tabla1 %>% 
  as_flex_table() %>% 
  save_as_docx(path = "Tabla1.docx")
  • Paso 1: Cargar paquete {flextable}

  • Paso 2: Se convierte a objeto de tipo flextable con la función as_flex_table().

  • Paso 3: Se guarda como word con la función save_as_docx()

Guardar tabla como documento MS Word (cont.)


  • El MS Word aparecerá en la carpeta del proyecto:

Guardar tabla como documento MS Word (cont.)


  • Y la tabla en Word lucirá así:

Guardar tabla como documento MS Excel


  • Usamos el paquete {huxtable}
library(huxtable)
  • Con la función as_hux_xlsx convertimos el objeto tbl_summary a un excel con un nombre de archivo que uno defina:
tabla1 %>% 
  as_hux_xlsx(file = "Tabla1.xlsx")
  • La tabla en excel se muestra a continuación:

gtsummary: tbl_summary y argumento by =

Agenda

  1. Reporte Reproducible

  2. tbl_summary() paso a paso

  3. gtsummary: tbl_summary y argumento by =

  4. Buenas y malas prácticas de reporte en investigación

  5. Misceláneas

{gtsummary}: tbl_summary y argumento by =

{gtsummary}: tbl_summary y argumento by =


Se puede usar la función tbl_summary() para comparar variables numéricas según grupos.

bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo)
  • Primero seleccionamos las variables numéricas y la variable de agrupación sexo.
edad tdosis_refuerzo IgG_Basal IgG_Final sexo
23 233 99.8  555 Femenino
24 232 41.3  549 Masculino
24 242 414    485
23 234 13.4  573 Femenino
24 236 4.83 474 Femenino
26 241 21.7  604 Femenino
25 201 8.7  533 Femenino
27 241 10.8  546 Femenino
25 212 417    474 Femenino
26 239 3.43 558 Femenino
28 246     378 Femenino
28 227 16.9  547 Masculino
27 235 133    479 Masculino
29 196 64.3  558 Femenino
27 235 20.6  456 Femenino
29 232 1.24 515 Femenino
29 236 5.01 534 Masculino
27 232 11.7  572 Femenino
27 233 75.5  535 Femenino
28 230 10.3  559 Femenino
29 247 25.3  527 Femenino
31 236 2.78 446 Femenino
29 237 20    535 Femenino
29 198 168    580 Masculino
30 233 8.18 582 Femenino
31 206 51.5  517 Femenino
31 206 14.3  437 Femenino
30 237 6.31 575 Masculino
33 242 158    599 Femenino
31 236 1.11 429 Masculino
32 227 71.6  530 Femenino
30 235 28.1  558 Femenino
31 247 139    536 Masculino
32 233 10.8  559 Femenino
33 213 12.3  422 Femenino
34 232 5.15 540 Femenino
32 197 40.7  290 Masculino
33 217 11.7  530 Femenino
32 187 9    570 Masculino
34 235 15.9  533 Masculino
33 228 27.5  481 Femenino
34 217 15.8  459 Femenino
33 222 1.84 493 Femenino
33 221 1.56 434 Femenino
33 190 156    585 Femenino
32 220 7.26 483 Femenino
32 236 38    472 Femenino
32 235 6.27 525 Masculino
32 231 2.69 529 Masculino
33 218 39.5  552 Masculino
32 218 13.6  472 Femenino
32 218 191    501 Femenino
34 213 12.8  519 Masculino
33 237 4.4  498 Femenino
36 235 16.6  541 Masculino
33 235 9.93 595 Femenino
35 220 109    573 Femenino
33 234 80.6  616 Femenino
33 221 8.88 572 Femenino
34 218 80.1  481 Femenino
33 212 31.5  437 Femenino
35 224 7.56 572 Masculino
34 237 71.8  581 Femenino
34 232 2.2  476 Masculino
36 221 58.6  441 Femenino
35 196 73.9  416 Femenino
34 234 16.1  504 Femenino
35 235 5.49 500 Femenino
36 236 7.64 509 Masculino
35 198 191    559 Femenino
32 233 36.2  556 Femenino
35 191 14.6  604 Masculino
37 233 8.74 536 Masculino
37 223 3.49 568 Femenino
34 238 87.3  519 Femenino
36 241 490    487 Masculino
36 205 3.95 446 Femenino
36 232 123    414 Masculino
36 234 17.3  592 Femenino
36 267 65.2  454 Femenino
36 195 434    543 Femenino
36 220 25.9  470 Femenino
36 204 35.1  410 Femenino
37 220 422    599 Femenino
37 217 19.8  540 Femenino
37 234 130    376 Masculino
37 203 5.75 491 Femenino
40 236 19.2  462 Masculino
38 225 122    526 Masculino
39 237 6.21 575 Femenino
37 236 163    573 Femenino
37 235 89.7  566 Femenino
38 202 35.4  412 Femenino
39 235 71.7  355 Femenino
39 235 327    594 Masculino
38 205 3.52 528 Masculino
40 223 59.4  502 Masculino
39 235 6.76 597 Femenino
39 206 137    473 Femenino
40 196 16.1  516 Femenino
42 226 18    515 Femenino
40 235 40.3  468 Femenino
41 235 113    604 Masculino
41 237 9.26 545 Femenino
39 232 0.31 530 Masculino
41 251 140    537 Femenino
42 205 18.4  429 Femenino
41 234 191    548 Femenino
41 205 3.83 524 Femenino
44 244 455    463 Femenino
42 225 2.53 479 Femenino
43 234 7.39 531 Femenino
41 205 97.2  474 Femenino
40 222 56.2  481 Femenino
42 235 54.6  550 Masculino
44 216 0.32 473 Femenino
43 204 9.2  424 Femenino
42 220 584    618 Femenino
45 220 11.1  487 Femenino
44 238 115    557 Femenino
42 207 2.07 327 Femenino
43 237 16.2  490 Femenino
43 252 78.2  552 Femenino
44 237 25.1  451 Masculino
45 235 4.9  494 Masculino
43 205 52.5  565 Masculino
44 234 56    532 Masculino
45 235 20.8  486 Femenino
44 201 6.72 428 Femenino
46 191 28.6  608 Femenino
45 237 5.84 508 Femenino
46 218 30.1  477 Masculino
44 212 19.1  498 Femenino
45 206 78.2  504 Femenino
44 202 16.9  535 Femenino
46 232 13.7  530 Femenino
45 238 25.6  589 Femenino
44 232 4.76 427 Femenino
47 205 8.08 481 Femenino
47 209 15.5  573 Femenino
46 196 6.14 507 Femenino
46 244 15.8  482 Femenino
47 246 86.4  490 Femenino
47 207 61.2  554 Femenino
46 214 154    416 Femenino
46 233 87.3  507 Masculino
46 234 67.5  575 Masculino
48 234 31.3  468 Femenino
48 232 158    549 Masculino
48 236 8.39 558 Masculino
47 205 0.46 523 Masculino
48 208 29    522 Femenino
48 229 11.6  552 Femenino
48 231 11.2  564 Femenino
50 235 7.07 559 Masculino
49 202 18.4  539 Masculino
51 228 3.46 390 Femenino
49 225 223    523 Masculino
50 236 11.5  435 Femenino
49 228 371    615 Femenino
49 205 7.88 531 Femenino
50 234 64.8  495 Femenino
49 237 4.49 509 Femenino
51 205 5.81 452 Masculino
49 233 2.86 500 Masculino
50 202 88.7  560 Femenino
50 240 36.6  545 Femenino
51 223 22.3  594 Femenino
51 234 22.3  509 Femenino
52 226 11    512 Femenino
51 231 70    413 Femenino
52 198 257    587 Femenino
51 234 2.9  526 Masculino
53 202 4.92 542 Femenino
52 240 350    546 Femenino
53 219 13.9  612 Femenino
53 235 152    551 Femenino
54 193 316    441 Femenino
55 233 1.99 490 Masculino
53 134 105    431 Masculino
54 236 12.3  537 Masculino
53 203 8.2  514 Femenino
53 196 49.3  454 Femenino
55 202 5.29 572 Masculino
55 233 6.62 519 Femenino
55 234 8.85 499 Femenino
53 211 7.96 493 Femenino
56 237 32    538 Femenino
55 196 7.17 607 Femenino
55 232 7.01 470 Masculino
54 203 73.1  505 Masculino
59 235 164    563 Masculino
55 193 203    520 Femenino
57 235 73    555 Masculino
58 202 4.77 468 Femenino
59 204 4.98 417 Femenino
59 233 39.8  540 Masculino
59 236 42.4  514 Femenino
59 206 25.3  471 Femenino
59 159 27.6  404 Femenino
55 234 6.17 451 Femenino
57 220 -2.19 406 Femenino
57 232 0.12 459 Masculino
59 239 4.09 479 Masculino
60 237 1.56 530 Masculino
57 226 14.2  499 Masculino
59 194 7.98 485 Femenino
58 235 1.48 525 Femenino
59 197 28    460 Femenino
58 234 1.88 463 Femenino
57 153 117    410 Femenino
59 233 2.18 469 Masculino
59 157 101    367 Femenino
59 235 220    551 Femenino
62 156 404    505 Masculino
61 218 309    598 Femenino
59 236 11.9  538 Masculino
59 233 142    540 Masculino
61 152 528    546 Femenino
59 151 35.9  439 Masculino
62 205 7.64 521 Femenino
59 236 290    499 Masculino
62 163 458    360 Masculino
61 199 66.5  476 Femenino
61 155 270    523 Masculino
62 238 2.08 468 Femenino
62 155 87.9  301 Femenino
62 221 42.8  514 Femenino
62 248 3.47 517 Femenino
63 157 202    521 Femenino
60 155 99.2  412 Masculino
61 165 34.3  354 Femenino
63 232 56.8  555 Femenino
62 159 119    423 Femenino
62 232 4.41 499 Femenino
64 154 529    544 Femenino
65 234 4.23 439 Femenino
66 162 518    475 Masculino
65 211 148    389 Femenino
65 235 79    403 Femenino
64 161 54.3  399 Masculino
64 236 7.63 441 Femenino
65 171 56.1  370 Femenino
64 168 85.4  403 Masculino
63 181 140    452 Masculino
65 237 32.5  564 Masculino
67 170 446    395 Masculino
64 180 131    359 Femenino
66 174 23.7  417 Femenino
66 225 306    568 Masculino
64 156 32.3  382 Masculino
67 168 465    474 Masculino
67 164 78.8  499 Femenino
68 183 195    434 Femenino
68 166 119    489 Masculino
68 206 0.75 479 Femenino
68 184 35.9  435 Femenino
68 234 12.7  402 Masculino
66 173 451    440 Masculino
70 242 11.8  472 Femenino
69 185 417    349 Masculino
70 176 24.9  333 Femenino
69 182 96    332 Masculino
71 200 270    408 Femenino
70 186 12.4  330 Femenino
69 184 180    408 Femenino
71 177 75.3  466 Masculino
71 184 362    405 Masculino
73 195 3.17 322 Femenino
72 195 40.6  447 Masculino
72 186 379    557 Masculino
72 179 47.1  510 Masculino
75 192 64.4  386 Masculino
73 185 391    523 Femenino
75 184 102    360 Masculino
74 171 312    468 Femenino
76 186 61.5  397 Femenino
75 192 66.1  471 Femenino
79 196 22.6  309 Masculino
77 200 57.8  363 Masculino
77 176 61.4  442 Femenino
78 176 18    246 Masculino
92 182 0.83 236 Femenino
94 185 48.7  440 Masculino
97 206 104    442 Femenino

{gtsummary}: tbl_summary y argumento by =


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary()
  • Primero seleccionamos las variables numéricas y la variable de agrupación sexo.

  • Si hacemos tbl_summary(), se generará una tabla descriptiva para toda la muestra.

{gtsummary}: tbl_summary y argumento by =


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo)
  • Primero seleccionamos las variables numéricas y la variable de agrupación sexo.

  • Si hacemos tbl_summary(), se generará una tabla descriptiva para toda la muestra.

  • El argumento by() genera una tabla descriptiva con las medidas de resumen por cada grupo.

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo) 

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2")) 
  • type: Especifica el tipo de variable para resumen.

    • Queremos reportar varios estadísticos para edad

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              statistic = list(
                edad ~ c("{mean} ± {sd}", "{median} ({p25}, {p75})")
              )) 
  • type: Especifica el tipo de variable para resumen.

    • Queremos reportar varios estadísticos para edad
  • statistic: Personaliza los estadísticos reportados.

    • Indicamos qué estadísticos queremos reportar para edad.

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              statistic = list(
                edad ~ c("{mean} ± {sd}", "{median} ({p25}, {p75})"), 
                IgG_Basal ~ "{mean} ± {sd}"
              )) 
  • type: Especifica el tipo de variable para resumen.

    • Queremos reportar varios estadísticos para edad
  • statistic: Personaliza los estadísticos reportados.

    • Indicamos qué estadísticos queremos reportar para edad.

    • Queremos reportar media y DE para IgG Basal.

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              statistic = list(
                edad ~ c("{mean} ± {sd}", "{median} ({p25}, {p75})"), 
                IgG_Basal ~ "{mean} ± {sd}"
              ), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              ))
  • type: Especifica el tipo de variable para resumen.

    • Queremos reportar varios estadísticos para edad
  • statistic: Personaliza los estadísticos reportados.

    • Indicamos qué estadísticos queremos reportar para edad.

    • Queremos reportar media y DE para IgG Basal.

  • label Personaliza las etiquetas de variable.

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              statistic = list(
                edad ~ c("{mean} ± {sd}", "{median} ({p25}, {p75})"), 
                IgG_Basal ~ "{mean} ± {sd}"
              ), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              ), 
              digits = list(
                c(IgG_Final, IgG_Basal) ~ 2
              ))
  • type: Especifica el tipo de variable para resumen.

  • statistic: Personaliza los estadísticos reportados.

  • label Personaliza las etiquetas de variable.

  • digits: Controla el número de decimales de redondeo.

    • Permitir que IgG (basal y final) se reporten con solo 2 decimales.

Personalizar tbl_summary() paso a paso


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              statistic = list(
                edad ~ c("{mean} ± {sd}", "{median} ({p25}, {p75})"), 
                IgG_Basal ~ "{mean} ± {sd}"
              ), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              ), 
              digits = list(
                c(IgG_Final, IgG_Basal) ~ 2, 
                edad ~ c(1, 2, 1, 2)
              )) 
  • type: Especifica el tipo de variable para resumen.

  • statistic: Personaliza los estadísticos reportados.

  • label Personaliza las etiquetas de variable.

  • digits: Controla el número de decimales de redondeo.

    • Edad que se reporte con 1 decimal la media y media y 2 decimales la SD y el IQR.

Más personalización de tbl_summary() con add_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              ))

Más personalización de tbl_summary() con add_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) %>% 
  add_overall()
  • add_overall: Agrega una columna con el resumen de características para toda la población de estudio.

Más personalización de tbl_summary() con add_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) %>% 
  add_overall() %>% 
  add_n()
  • add_overall: Agrega una columna con el resumen de características para toda la población de estudio.

  • add_n(): Agrega una columna con el tamaño de muestra efectivo (excluyendo los datos perdidos)

Más personalización de tbl_summary() con modify_()


  • Podemos modificar el nombre de las cabeceras, pero primero hay que saber cómo están guardadas.

  • Creamos la tabla cruda y la guardamos con un nombre:

bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) -> tabla

tabla

Más personalización de tbl_summary() con modify_()


  • Podemos modificar el nombre de las cabeceras, pero primero hay que saber cómo están guardadas.

  • Creamos la tabla cruda y la guardamos con un nombre:

bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) -> tabla

tabla
  • Luego, consultamos los nombres de cabeceras internos que tiene el objeto tbl_summary:
show_header_names(tabla)



Column Name   Column Header         
------------  ----------------------
label         **Characteristic**    
stat_1        **Femenino**, N = 189 
stat_2        **Masculino**, N = 95 

  • Podemos editar los nombres de las cabeceras llamándolos como label, stat_1 y stat_2.

Más personalización de tbl_summary() con modify_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) 
  • modify_header(): Edita los nombres de las cabeceras.

Más personalización de tbl_summary() con modify_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) %>% 
  modify_header(
    label ~ "Variables", 
    stat_1 ~ "Female", 
    stat_2 ~ "Male"
  )
  • modify_header(): Edita los nombres de las cabeceras.

Más personalización de tbl_summary() con modify_()


bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) %>% 
  modify_header(
    label ~ "Variables", 
    stat_1 ~ "Female", 
    stat_2 ~ "Male"
  )
  • modify_header(): Edita los nombres de las cabeceras.

    • Podemos editar el contenido de estas con {}

      • Por ejemplo, poner “n = {n}”

Más personalización de tbl_summary() con modify_()


:::: {.columns}

bd_inmuno %>% 
  select(edad, tdosis_refuerzo, IgG_Basal, IgG_Final, sexo) %>% 
  tbl_summary(by = sexo, 
              type = list(edad ~ "continuous2"), 
              label = list(
                edad ~ "Age, years", 
                tdosis_refuerzo ~ "Time between second and third dose", 
                IgG_Basal ~ "IgG pre booster", 
                IgG_Final ~ "IgG post booster"
              )) %>% 
  modify_header(
    label ~ "Variables", 
    stat_1 ~ "Female (n = {n})", 
    stat_2 ~ "Male (n = {n})"
  )  
  • modify_header(): Edita los nombres de las cabeceras.

    • Podemos editar el contenido de estas con {}

      • Por ejemplo, poner “n = {n}”

::: {.column width=‘50%’}

Buenas y malas prácticas de reporte en investigación

Agenda

  1. Reporte Reproducible

  2. tbl_summary() paso a paso

  3. gtsummary: tbl_summary y argumento by =

  4. Buenas y malas prácticas de reporte en investigación

  5. Misceláneas

Buenas y malas prácticas de reporte en investigación

Recomendaciones de reporte

  • No reporte valores p innecesarios, que no respondan sus preguntas de investigación pre-definidas.

  • Es una mala práctica reportar tablas comparativas descriptivas con valores p. Lamentablemente es muy difundida.

  • Varias guías, comenzando por STROBE (para observacionales) y CONSORT (para ensayos clínicos) explícitamente recomiendan en contra de reportar estas tablas. Solo haga una comparación descriptiva de los resultados de la tabla.

gtsummary and p-values

  • Se puede agregar el valor p en las tablas de gtsummary:
library(gtsummary)
datos %>%
  dplyr::select(treat, age, race, married2, weight, height, e2) %>% 
  tbl_summary(
    by = treat
  ) %>%  
  add_p()
Characteristic Dosis 1, N = 341 Dosis 2, N = 381 Placebo, N = 341 p-value2
Age, years 31.0 (27.0, 38.0) 35.0 (30.0, 37.0) 34.0 (31.3, 37.0) 0.8
Race



    Mestiza 34 (100%) 38 (100%) 34 (100%)
Marital status, recat


0.4
    With couple 14 (41%) 22 (58%) 16 (47%)
    Without couple 20 (59%) 16 (42%) 18 (53%)
Weight, kg 60 (56, 65) 61 (54, 66) 59 (56, 65) >0.9
    Unknown 1 1 1
Height, m


0.2
    1.3 0 (0%) 0 (0%) 1 (3.0%)
    1.4 1 (3.0%) 6 (16%) 5 (15%)
    1.5 22 (67%) 17 (46%) 13 (39%)
    1.6 9 (27%) 9 (24%) 10 (30%)
    1.7 1 (3.0%) 5 (14%) 4 (12%)
    Unknown 1 1 1
Estradiol 95 (74, 128) 96 (61, 147) 90 (50, 129) 0.6
1 Median (IQR); n (%)
2 Kruskal-Wallis rank sum test; Pearson’s Chi-squared test; Fisher’s exact test

¿Qué dice STROBE?

  • La guía “Strengthening the reporting of observational studies in epidemiology (STROBE) statement” da algunas recomendaciones para tablas tipo 1:

¿Qué dice STROBE?

  • STROBE recomienda en contra de reportar valores p en las tablas descriptivas!!
https://journals.lww.com/epidem/Fulltext/2007/11000/Strengthening_the_Reporting_of_Observational.28.aspx
  • Lamentablemente sigue siendo una mala práctica muy difundida. Evitemos esta mala práctica.

¿Y valores p en la Tabla 11 de ensayos clínicos?

  • El “Consolidated Standards of Reporting Trials (CONSORT)” recomienda no usar valores p ni métodos de inferencia estadística en la Tabla 1.

  • Evaluar el “balance” y la “adecuada” asignación aleatoria en la Tabla 1 de un ensayo clínico es conocido como: “Falacia de la tabla 1”.

  • Para más información revise el siguiente artículo: https://www.bmj.com/content/340/bmj.c869

Misceláneas

Agenda

  1. Reporte Reproducible

  2. tbl_summary() paso a paso

  3. gtsummary: tbl_summary y argumento by =

  4. Buenas y malas prácticas de reporte en investigación

  5. Misceláneas

{gtsummary}: Misceláneas

Otras formas de imprimir tablas

  • Tablas con kable() y kableExtra() de paquete {knitr}.

  • Tablas de {gt} y {flextable}.

Reproducibilidad y gráficos

  • Crear gráficos de alta calidad con ggplot2

  • Guardar gráficos especificando sus parámetros con ggsave

  • Ensamblar gráficos con {patchwork}

  • Imprimir imágenes en Quarto

Superpoderes de Quarto

  • Código dentro de texto.

  • Información extra sobre Quarto

  • Configuraciones básicas adicionales.

  • Temas de Quarto

Hagamos una pausa


Tomemos un descanso de 5 minutos

Estire las piernas

Deje de ver las pantallas

… cualquier , las del celular también.

05:00

¡Gracias!
¿Preguntas?




@psotob91

https://github.com/psotob91

percys1991@gmail.com